/*
 *  Copyright 2003 by Spectrum Digital Incorporated.
 *  All rights reserved. Property of Spectrum Digital Incorporated.
 */

/*
 *  ======== evmdm642_aic23_registers.c ========
 *  EVMDM642_AIC23_rset() and EVMDM642_AIC23_rget() implementation
 */
 
#include <csl.h>
#include <csl_i2c.h>

#include <evmdm642.h>
#include <evmdm642_aic23.h>

/* Internal codec state used to simulate read/write functionality */
static EVMDM642_AIC23_Config codecstate = EVMDM642_AIC23_DEFAULTCONFIG;

static I2C_Config aic23XmtCfg = {
    0x0000007f, /* I2COAR -    Not used if master */
    0x00000000, /* I2CIER -    Disable interrupts, use polling */
    0x0000001b, /* I2CCLKL -   Low period for 100KHz operation */
    0x0000001b, /* I2CCLKH -   High period for 100KHz operation */
    0x00000002, /* I2CCNT -    Data words per transmission */
    0x0000001a, /* I2CSAR -    Slave address */
    0x00004ea0, /* I2CMDR -    Mode */
    0x00000019  /* I2CPSC -    Prescale 300MHz to 12MHz */
};

/*
 *  ======== EVMDM642_AIC23_rset ========
 *  Set codec register regnum to value regval
 */
void EVMDM642_AIC23_rset(EVMDM642_AIC23_CodecHandle hCodec, Uint16 regnum, Uint16 regval)
{
    Uint16 data;
    I2C_Config prevI2CCfg;
    
    /* Mask off lower 9 bits */
    regval &= 0x1ff;
    
    /* Set transmit data */
    data = (regnum << 9) | regval;
    
    /* Wait until bus is free */
    while (I2C_bb(EVMDM642_I2C_hI2C));
    
    /* Save old settings */
    I2C_getConfig(EVMDM642_I2C_hI2C, &prevI2CCfg);
    
    /* Restore settings for AIC23 */
    I2C_config(EVMDM642_I2C_hI2C, &aic23XmtCfg);

    /* Submit the MSB for transmit */
    I2C_RSETH(EVMDM642_I2C_hI2C, I2CDXR, (data >> 8) & 0xff);
    
    /* Generate start condition, starts transmission */
    I2C_start(EVMDM642_I2C_hI2C);
    
    /* Wait until MSB transmit is done */
    while(!I2C_xrdy(EVMDM642_I2C_hI2C));

    /* Submit the LSB for transmit */ 
    I2C_writeByte(EVMDM642_I2C_hI2C, data & 0xff);
        
    /* Generate stop condition */
    I2C_sendStop(EVMDM642_I2C_hI2C);  

    /* Wait until bus is free */
    while (I2C_bb(EVMDM642_I2C_hI2C));
    
    /* Save register value if regnum is in range */
    if (regnum < EVMDM642_AIC23_NUMREGS)
        codecstate.regs[regnum] = regval;

    /* Short delay for AIC23 to accept command */        
    EVMDM642_waitusec(20);

    /* Reconfigure I2C with old settings */
    I2C_config(EVMDM642_I2C_hI2C, &prevI2CCfg);
}

/*
 *  ======== EVMDM642_AIC23_rget ========
 *  Return value of codec register regnum
 */
Uint16 EVMDM642_AIC23_rget(EVMDM642_AIC23_CodecHandle hCodec, Uint16 regnum)
{
    if (regnum < EVMDM642_AIC23_NUMREGS)
        return codecstate.regs[regnum];
    else
        return 0;    
}

/*
 *  ======== EVMDM642_AIC23_config ========
 *  Set the default codec register config values
 */
void EVMDM642_AIC23_config(EVMDM642_AIC23_CodecHandle hCodec, EVMDM642_AIC23_Config *Config)
{
    int i;
    
    /* Use default parameters if none are given */
    if (Config == NULL)
    	Config = &codecstate;
    
    /* Reset the codec */
    EVMDM642_AIC23_rset(hCodec, 15, 0);
    
    /* Assign each register */
    for (i = 0; i < EVMDM642_AIC23_NUMREGS; i++)
    {
        if (i != 6)
            EVMDM642_AIC23_rset(hCodec, i, Config -> regs[i]);
    }
    EVMDM642_AIC23_rset(hCodec, 6, Config -> regs[6]);
}
